--------------------------------------------------------------------------------
--                           IntSquarer_8_F400_uid4
-- This operator is part of the Infinite Virtual Library FloPoCoLib
-- All rights reserved 
-- Authors: Bogdan Pasca (2009)
--------------------------------------------------------------------------------
-- Pipeline depth: 1 cycles

library ieee; 
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library work;
entity IntSquarer_8_F400_uid4 is
   port ( clk, rst, ce : in std_logic;
          X : in  std_logic_vector(7 downto 0);
          R : out  std_logic_vector(15 downto 0)   );
end entity;

architecture arch of IntSquarer_8_F400_uid4 is
signal sX, sX_d1 :  std_logic_vector(7 downto 0);
signal sY, sY_d1 :  std_logic_vector(7 downto 0);
begin
   process(clk)
      begin
         if clk'event and clk = '1' then
            if ce = '1' then
               sX_d1 <=  sX;
               sY_d1 <=  sY;
            end if;
         end if;
      end process;
   sX <= X;
   sY <= X;
   ----------------Synchro barrier, entering cycle 1----------------
   R <= sX_d1 * sY_d1;
end architecture;

--------------------------------------------------------------------------------
--                           IntAdder_17_f400_uid8
--                    (IntAdderAlternative_17_F400_uid12)
-- This operator is part of the Infinite Virtual Library FloPoCoLib
-- All rights reserved 
-- Authors: Bogdan Pasca, Florent de Dinechin (2008-2010)
--------------------------------------------------------------------------------
-- Pipeline depth: 0 cycles

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library std;
use std.textio.all;
library work;

entity IntAdder_17_f400_uid8 is
   port ( clk, rst, ce : in std_logic;
          X : in  std_logic_vector(16 downto 0);
          Y : in  std_logic_vector(16 downto 0);
          Cin : in  std_logic;
          R : out  std_logic_vector(16 downto 0)   );
end entity;

architecture arch of IntAdder_17_f400_uid8 is
begin
   process(clk)
      begin
         if clk'event and clk = '1' then
            if ce = '1' then
            end if;
         end if;
      end process;
   --Alternative
    R <= X + Y + Cin;
end architecture;

--------------------------------------------------------------------------------
--                               FPSquare_BF16
--                         (FPSquare_8_7_7_F400_uid2)
-- This operator is part of the Infinite Virtual Library FloPoCoLib
-- All rights reserved 
-- Authors: Bogdan Pasca (2009)
--------------------------------------------------------------------------------
-- Pipeline depth: 3 cycles

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_arith.all;
use ieee.std_logic_unsigned.all;
library std;
use std.textio.all;
library work;

entity FPSquare_BF16 is
   port ( clk, rst, ce : in std_logic;
          X : in  std_logic_vector(8+7+2 downto 0);
          R : out  std_logic_vector(8+7+2 downto 0)   );
end entity;

architecture arch of FPSquare_BF16 is
   component IntSquarer_8_F400_uid4 is
      port ( clk, rst, ce : in std_logic;
             X : in  std_logic_vector(7 downto 0);
             R : out  std_logic_vector(15 downto 0)   );
   end component;

   component IntAdder_17_f400_uid8 is
      port ( clk, rst, ce : in std_logic;
             X : in  std_logic_vector(16 downto 0);
             Y : in  std_logic_vector(16 downto 0);
             Cin : in  std_logic;
             R : out  std_logic_vector(16 downto 0)   );
   end component;

signal exc, exc_d1, exc_d2 :  std_logic_vector(1 downto 0);
signal exp :  std_logic_vector(7 downto 0);
signal frac :  std_logic_vector(7 downto 0);
signal extExponent :  std_logic_vector(9 downto 0);
signal negBias :  std_logic_vector(9 downto 0);
signal extExpPostBiasSub, extExpPostBiasSub_d1, extExpPostBiasSub_d2 :  std_logic_vector(9 downto 0);
signal sqrFrac, sqrFrac_d1 :  std_logic_vector(15 downto 0);
signal sticky :  std_logic;
signal guard :  std_logic;
signal fracULP :  std_logic;
signal extExp :  std_logic_vector(9 downto 0);
signal finalFrac :  std_logic_vector(6 downto 0);
signal concatExpFrac :  std_logic_vector(16 downto 0);
signal addCin :  std_logic;
signal postRound, postRound_d1 :  std_logic_vector(16 downto 0);
signal excConcat, excConcat_d1 :  std_logic_vector(3 downto 0);
signal excR :  std_logic_vector(1 downto 0);
begin
   process(clk)
      begin
         if clk'event and clk = '1' then
            if ce = '1' then
               exc_d1 <=  exc;
               exc_d2 <=  exc_d1;
               extExpPostBiasSub_d1 <=  extExpPostBiasSub;
               extExpPostBiasSub_d2 <=  extExpPostBiasSub_d1;
               sqrFrac_d1 <=  sqrFrac;
               postRound_d1 <=  postRound;
               excConcat_d1 <=  excConcat;
            end if;
         end if;
      end process;
   exc <= X(17 downto 16);
   exp <= X(14 downto 7);
   frac <= "1" & X(6 downto 0);
   extExponent<="0" & exp & "0";
   negBias<=CONV_STD_LOGIC_VECTOR(896,10);
   extExpPostBiasSub <= extExponent + negBias + '1';
      FractionSquarer: IntSquarer_8_F400_uid4  -- pipelineDepth=1 maxInDelay=0
      port map ( clk  => clk,
                 rst  => rst,
                 ce => ce,
                 R => sqrFrac,
                 X => frac);
   ----------------Synchro barrier, entering cycle 1----------------
   ----------------Synchro barrier, entering cycle 2----------------
   sticky<='0' when sqrFrac_d1(5 downto 0)="000000"else '1';
   guard <= sqrFrac_d1(6) when sqrFrac_d1(15)='0' else sqrFrac_d1(7);
   fracULP<=sqrFrac_d1(7) when sqrFrac_d1(15)='0' else sqrFrac_d1(8);
   extExp <= extExpPostBiasSub_d2 + sqrFrac_d1(15);
   finalFrac<= sqrFrac_d1(14 downto 8) when sqrFrac_d1(15)='1' else 
      sqrFrac_d1(13 downto 7);
   concatExpFrac <= extExp & finalFrac;
   addCin <= (guard and sticky) or (fracULP and guard and not(sticky));
   Rounding_Instance: IntAdder_17_f400_uid8  -- pipelineDepth=0 maxInDelay=1.30344e-09
      port map ( clk  => clk,
                 rst  => rst,
                 ce => ce,
                 Cin => addCin,
                 R => postRound,
                 X => concatExpFrac,
                 Y => "00000000000000000");
   excConcat <= exc_d2 & postRound(16 downto 15);
   ----------------Synchro barrier, entering cycle 3----------------
   with excConcat_d1 select 
   excR<="00" when "0000",
      "00" when "0001",
      "00" when "0010",
      "00" when "0011",
      "01" when "0100",
      "10" when "0101",
      "00" when "0110",
      "00" when "0111",
      "10" when "1000",
      "10" when "1001",
      "10" when "1010",
      "10" when "1011",
      "11" when "1100",
      "11" when "1101",
      "11" when "1110",
      "11" when "1111",
      "11" when others;
   R <= excR &  "0"  & postRound_d1(14 downto 7) & postRound_d1(6 downto 0);
end architecture;

